
from markupsafe import Markup, escape_silent as escape

__metaclass__ = type

empty = 'area base basefont br col frame hr img input isindex link meta param'
empty = set(empty.split())


def _make_tag(tag, args, kw):
    if kw.has_key('_'):
        assert not args, "The special '_' keyword argument cannot be used "\
                         'in conjunction with non-keyword arguments'
        args = kw.pop('_')
    close = kw.pop('_close', True)
    attrs = [' %s="%s"' % (k.lower(), escape(v))
             for k, v in sorted(kw.iteritems())
             if v is not None]

    start = '<%s%s' % (tag, ''.join(attrs))

    if not args and tag in empty and close:
        content = ''
        end = ' />'
    else:
        start += '>'
        content = ''.join(escape(x) for x in args)
        end = close and '</%s>'%tag or ''

    return Markup(start+content+end)


class Literal:
    def __call__(self, *args):
        return Markup(*args)

    def __html__(self):
        raise NotImplementedError


class Tag(Literal):
    def __init__(self, name):
        self.name = name

    def __call__(__self, *args, **kw):
        return _make_tag(__self.name, args, kw)

    def __str__(self):
        return Markup('<%s />' % self.name)

    def __html__(self):
        return str(self)


class Builder:
    literal = Literal()

    def __getattr__(self, name):
        if name.startswith('_'):
            raise AttributeError
        x = self.__dict__[name] = Tag(name.lower())
        return x

    def __call__(self, *args):
        return Markup(''.join(escape(x) for x in args))

    def tag(__self, __tag, *args, **kw):
        return _make_tag(__tag, args, kw)


HTML = Builder()


